#include "triangle_mesh.h"

#include <vector>

#include "triangle.h"
#include "geometry/aabb.h"
#include "geometry/vector3.h"


namespace venus {
TriangleMesh::~TriangleMesh() {
  delete[] points_;
  delete[] normals_;
  delete[] tex_coords_;
  delete[] vertex_indices_;
  triangle_count_ = 0; 
  vertex_count_ = 0;
}		

void TriangleMesh::Scale(float scale) {
  for (int i = 0; i < vertex_count_; ++i) {
    this->set_point(i, this->point(i) * scale);
  }
  bound_need_update_ = true;
}

void TriangleMesh::Scale2Size(float size) {
  AABB box = this->Bound();
  Vector3 box_size = box.size();
  float max_size = std::max(std::max(box_size.x, box_size.y), box_size.z);
  this->Scale(size / max_size);
}

void TriangleMesh::Translate(const Vector3 &offset) {
  for (int i = 0; i < vertex_count_; ++i) {
    this->set_point(i, this->point(i) + offset);
  }
  bound_need_update_ = true;
}
void TriangleMesh::Translate2Pos(const Point &pos) {
  AABB box = this->Bound();
  Point center = box.minP + box.size() / 2;
  Vector3 offset = pos - center;
  this->Translate(offset);
}

void TriangleMesh::GetTriangles(ShapeSet *triangles) const {
  triangles->reserve(triangles->size() + triangle_count_);
  int *vert_index_ptr = this->vertex_indices_;
  for (int i = 0; i < triangle_count_; ++i) {
    triangles->push_back(SharedPtr<Shape>(new Triangle( 
            const_cast<TriangleMesh*>(this), vert_index_ptr)));
    vert_index_ptr += 3;
  }
}

void TriangleMesh::ComputeBound() const {
  bound_ = AABB();
  for (int i = 0; i < vertex_count_; ++i) {
    bound_.Union(points_[i]);
  }
  bound_need_update_ = false;
}

AABB TriangleMesh::Bound() const {
  if (bound_need_update_) this->ComputeBound();
  return bound_;
}
}//namespace venus
